/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Persistencia;

import Persistencia.exceptions.NonexistentEntityException;
import Persistencia.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import motoressa.EncabezadoDePedido;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.transaction.UserTransaction;
import motoressa.Cliente;
import motoressa.Turno;

/**
 *
 * @author HP
 */
public class ClienteJpaController implements Serializable {

    public ClienteJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public ClienteJpaController() {
        emf=Persistence.createEntityManagerFactory("MotoresSAPU");
    }
    
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Cliente cliente) throws PreexistingEntityException, Exception {
        if (cliente.getMisEncabezadosDePedidos() == null) {
            cliente.setMisEncabezadosDePedidos(new ArrayList<EncabezadoDePedido>());
        }
        if (cliente.getMisTurnos() == null) {
            cliente.setMisTurnos(new ArrayList<Turno>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            List<EncabezadoDePedido> attachedMisEncabezadosDePedidos = new ArrayList<EncabezadoDePedido>();
            for (EncabezadoDePedido misEncabezadosDePedidosEncabezadoDePedidoToAttach : cliente.getMisEncabezadosDePedidos()) {
                misEncabezadosDePedidosEncabezadoDePedidoToAttach = em.getReference(misEncabezadosDePedidosEncabezadoDePedidoToAttach.getClass(), misEncabezadosDePedidosEncabezadoDePedidoToAttach.getCodigo());
                attachedMisEncabezadosDePedidos.add(misEncabezadosDePedidosEncabezadoDePedidoToAttach);
            }
            cliente.setMisEncabezadosDePedidos(attachedMisEncabezadosDePedidos);
            List<Turno> attachedMisTurnos = new ArrayList<Turno>();
            for (Turno misTurnosTurnoToAttach : cliente.getMisTurnos()) {
                misTurnosTurnoToAttach = em.merge(misTurnosTurnoToAttach);
                attachedMisTurnos.add(misTurnosTurnoToAttach);
            }
            cliente.setMisTurnos(attachedMisTurnos);
            em.persist(cliente);
            for (EncabezadoDePedido misEncabezadosDePedidosEncabezadoDePedido : cliente.getMisEncabezadosDePedidos()) {
                Cliente oldMiClienteOfMisEncabezadosDePedidosEncabezadoDePedido = misEncabezadosDePedidosEncabezadoDePedido.getMiCliente();
                misEncabezadosDePedidosEncabezadoDePedido.setMiCliente(cliente);
                misEncabezadosDePedidosEncabezadoDePedido = em.merge(misEncabezadosDePedidosEncabezadoDePedido);
                if (oldMiClienteOfMisEncabezadosDePedidosEncabezadoDePedido != null) {
                    oldMiClienteOfMisEncabezadosDePedidosEncabezadoDePedido.getMisEncabezadosDePedidos().remove(misEncabezadosDePedidosEncabezadoDePedido);
                    oldMiClienteOfMisEncabezadosDePedidosEncabezadoDePedido = em.merge(oldMiClienteOfMisEncabezadosDePedidosEncabezadoDePedido);
                }
            }
            for (Turno misTurnosTurno : cliente.getMisTurnos()) {
                Cliente oldMiClienteOfMisTurnosTurno = misTurnosTurno.getMiCliente();
                misTurnosTurno.setMiCliente(cliente);
                misTurnosTurno = em.merge(misTurnosTurno);
                if (oldMiClienteOfMisTurnosTurno != null) {
                    oldMiClienteOfMisTurnosTurno.getMisTurnos().remove(misTurnosTurno);
                    oldMiClienteOfMisTurnosTurno = em.merge(oldMiClienteOfMisTurnosTurno);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findCliente(cliente.getDni()) != null) {
                throw new PreexistingEntityException("Cliente " + cliente + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Cliente cliente) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Cliente persistentCliente = em.find(Cliente.class, cliente.getDni());
            List<EncabezadoDePedido> misEncabezadosDePedidosOld = persistentCliente.getMisEncabezadosDePedidos();
            List<EncabezadoDePedido> misEncabezadosDePedidosNew = cliente.getMisEncabezadosDePedidos();
            List<Turno> misTurnosOld = persistentCliente.getMisTurnos();
            List<Turno> misTurnosNew = cliente.getMisTurnos();
            List<EncabezadoDePedido> attachedMisEncabezadosDePedidosNew = new ArrayList<EncabezadoDePedido>();
            for (EncabezadoDePedido misEncabezadosDePedidosNewEncabezadoDePedidoToAttach : misEncabezadosDePedidosNew) {
                misEncabezadosDePedidosNewEncabezadoDePedidoToAttach = em.getReference(misEncabezadosDePedidosNewEncabezadoDePedidoToAttach.getClass(), misEncabezadosDePedidosNewEncabezadoDePedidoToAttach.getCodigo());
                attachedMisEncabezadosDePedidosNew.add(misEncabezadosDePedidosNewEncabezadoDePedidoToAttach);
            }
            misEncabezadosDePedidosNew = attachedMisEncabezadosDePedidosNew;
            cliente.setMisEncabezadosDePedidos(misEncabezadosDePedidosNew);
            List<Turno> attachedMisTurnosNew = new ArrayList<Turno>();
            for (Turno misTurnosNewTurnoToAttach : misTurnosNew) {
                misTurnosNewTurnoToAttach = em.merge(misTurnosNewTurnoToAttach);
                attachedMisTurnosNew.add(misTurnosNewTurnoToAttach);
            }
            misTurnosNew = attachedMisTurnosNew;
            cliente.setMisTurnos(misTurnosNew);
            cliente = em.merge(cliente);
            for (EncabezadoDePedido misEncabezadosDePedidosOldEncabezadoDePedido : misEncabezadosDePedidosOld) {
                if (!misEncabezadosDePedidosNew.contains(misEncabezadosDePedidosOldEncabezadoDePedido)) {
                    misEncabezadosDePedidosOldEncabezadoDePedido.setMiCliente(null);
                    misEncabezadosDePedidosOldEncabezadoDePedido = em.merge(misEncabezadosDePedidosOldEncabezadoDePedido);
                }
            }
            for (EncabezadoDePedido misEncabezadosDePedidosNewEncabezadoDePedido : misEncabezadosDePedidosNew) {
                if (!misEncabezadosDePedidosOld.contains(misEncabezadosDePedidosNewEncabezadoDePedido)) {
                    Cliente oldMiClienteOfMisEncabezadosDePedidosNewEncabezadoDePedido = misEncabezadosDePedidosNewEncabezadoDePedido.getMiCliente();
                    misEncabezadosDePedidosNewEncabezadoDePedido.setMiCliente(cliente);
                    misEncabezadosDePedidosNewEncabezadoDePedido = em.merge(misEncabezadosDePedidosNewEncabezadoDePedido);
                    if (oldMiClienteOfMisEncabezadosDePedidosNewEncabezadoDePedido != null && !oldMiClienteOfMisEncabezadosDePedidosNewEncabezadoDePedido.equals(cliente)) {
                        oldMiClienteOfMisEncabezadosDePedidosNewEncabezadoDePedido.getMisEncabezadosDePedidos().remove(misEncabezadosDePedidosNewEncabezadoDePedido);
                        oldMiClienteOfMisEncabezadosDePedidosNewEncabezadoDePedido = em.merge(oldMiClienteOfMisEncabezadosDePedidosNewEncabezadoDePedido);
                    }
                }
            }
            for (Turno misTurnosOldTurno : misTurnosOld) {
                if (!misTurnosNew.contains(misTurnosOldTurno)) {
                    misTurnosOldTurno.setMiCliente(null);
                    misTurnosOldTurno = em.merge(misTurnosOldTurno);
                }
            }
            for (Turno misTurnosNewTurno : misTurnosNew) {
                if (!misTurnosOld.contains(misTurnosNewTurno)) {
                    Cliente oldMiClienteOfMisTurnosNewTurno = misTurnosNewTurno.getMiCliente();
                    misTurnosNewTurno.setMiCliente(cliente);
                    misTurnosNewTurno = em.merge(misTurnosNewTurno);
                    if (oldMiClienteOfMisTurnosNewTurno != null && !oldMiClienteOfMisTurnosNewTurno.equals(cliente)) {
                        oldMiClienteOfMisTurnosNewTurno.getMisTurnos().remove(misTurnosNewTurno);
                        oldMiClienteOfMisTurnosNewTurno = em.merge(oldMiClienteOfMisTurnosNewTurno);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = cliente.getDni();
                if (findCliente(id) == null) {
                    throw new NonexistentEntityException("The cliente with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Cliente cliente;
            try {
                cliente = em.getReference(Cliente.class, id);
                cliente.getDni();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The cliente with id " + id + " no longer exists.", enfe);
            }
            List<EncabezadoDePedido> misEncabezadosDePedidos = cliente.getMisEncabezadosDePedidos();
            for (EncabezadoDePedido misEncabezadosDePedidosEncabezadoDePedido : misEncabezadosDePedidos) {
                misEncabezadosDePedidosEncabezadoDePedido.setMiCliente(null);
                misEncabezadosDePedidosEncabezadoDePedido = em.merge(misEncabezadosDePedidosEncabezadoDePedido);
            }
            List<Turno> misTurnos = cliente.getMisTurnos();
            for (Turno misTurnosTurno : misTurnos) {
                misTurnosTurno.setMiCliente(null);
                misTurnosTurno = em.merge(misTurnosTurno);
            }
            em.remove(cliente);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Cliente> findClienteEntities() {
        return findClienteEntities(true, -1, -1);
    }

    public List<Cliente> findClienteEntities(int maxResults, int firstResult) {
        return findClienteEntities(false, maxResults, firstResult);
    }

    private List<Cliente> findClienteEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Cliente as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Cliente findCliente(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Cliente.class, id);
        } finally {
            em.close();
        }
    }

    public int getClienteCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Cliente as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
